home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Tetris Light 1.0 / source / controls.c < prev    next >
Text File  |  1993-07-18  |  8KB  |  320 lines

  1. /**********************************************************************\
  2.  
  3. File:        controls.c
  4.  
  5. Purpose:    Module contains code relating to the controls for playing
  6.             the game, and data relating to the user settings of the game.
  7.             
  8.  
  9. ``Tetris Light'' - a simple implementation of a Tetris game.
  10. Copyright (C) 1993 Hoylen Sue
  11.  
  12. This program is free software; you can redistribute it and/or modify
  13. it under the terms of the GNU General Public License as published by
  14. the Free Software Foundation; either version 2 of the License, or
  15. (at your option) any later version.
  16.  
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. GNU General Public License for more details.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with this program; see the file COPYING.  If not, write to the
  24. Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26. \**********************************************************************/
  27.  
  28. #include "local.h"
  29.  
  30. #include "controls.h"
  31. #include "dialutil.h"
  32. #include "pstring.h"
  33. #include "resources.h"
  34. #include "windows.h"
  35.  
  36. /*--------------------------------------------------------------------*/
  37.  
  38. /* Control keys and playing preferences. */
  39.  
  40. struct Ctrls ctrls = {
  41.     { 38, 40, 37, 49 },
  42.     { 'J', 'K', 'L', ' ' },
  43.     TRUE,    /* Show next piece */
  44.     TRUE    /* Sound on */
  45. };
  46.  
  47. /*--------------------------------------------------------------------*/
  48.  
  49. /* Static globals for interface for setting control keys */
  50.  
  51. static INTEGER key_target = 0;
  52. static FontInfo key_font_info;
  53. static Handle key_icon;
  54. static Handle key_pressed_icon;
  55.  
  56. /*====================================================================*/
  57.  
  58. Boolean controls_init(void)
  59. /* Initializes this module.  Loads up the icons for displaying the
  60.    control key editing dialog.  Returns FALSE on success, TRUE if it
  61.    failed. */
  62. {
  63.     /* Load icons */
  64.     
  65.     key_icon = GetIcon(KEY_ICON_ID);
  66.     key_pressed_icon = GetIcon(KEY_PRESSED_ICON_ID);
  67.     if (! key_icon || ! key_pressed_icon)
  68.         return TRUE; /* Failed */
  69.         
  70.     return FALSE; /* Success */
  71. }
  72.  
  73. /*--------------------------------------------------------------------*/
  74.  
  75. static pascal void key_item_proc(WindowPtr wind, INTEGER item)
  76. /* Draw routine for the key userItem.  Draws the key using the 
  77.    appropriately highlighted icon, and draws the character of it
  78.    in the centre. */
  79. {
  80.     INTEGER dummy;
  81.     Rect box;
  82.     Handle h;
  83.     Str255 str;
  84.     
  85.     switch (ctrls.sym[item - KEYS_ITEM_LEFT_KEY]) {
  86.     case ' ':
  87.         pstrcpy(str, "\pSP");
  88.         break;
  89.     default:
  90.         str[0] = 1;
  91.         str[1] = ctrls.sym[item - KEYS_ITEM_LEFT_KEY];
  92.         break;
  93.     }
  94.     
  95.     GetDItem(wind, item, &dummy, &h, &box);
  96.     
  97.     PlotIcon(&box, (key_target != item) ? key_icon : key_pressed_icon);
  98.     MoveTo((box.left + box.right - StringWidth(str)) / 2, 
  99.            (box.top + box.bottom + key_font_info.ascent - key_font_info.descent) / 2);
  100.     TextMode(patXor);
  101.     DrawString(str);
  102. }
  103.  
  104. /*--------------------------------------------------------------------*/
  105.  
  106. static pascal Boolean keys_filter_proc(DialogPtr dp, EventRecord *evt,
  107.                                        INTEGER *itemhit)
  108. /* Filter proc for control keys dialog. */
  109. {
  110.     switch (evt->what) {
  111.     case mouseDown:
  112.         if (key_target != 0) {
  113.             /* Unhighlight any currently highlighted key */
  114.             
  115.             register INTEGER old = key_target;
  116.             
  117.             key_target = 0;
  118.             SetPort(dp);
  119.             key_item_proc(dp, old);
  120.             return FALSE;    /* [sic] yes, return FALSE */
  121.         }
  122.         break;
  123.         
  124.     case keyDown:
  125.         if ((evt->message & keyCodeMask) >> 8 == ESC_KEY) {
  126.             simulate_key_hit(dp, Cancel);
  127.             *itemhit = Cancel;
  128.             return TRUE;
  129.         }
  130.         
  131.         switch (evt->message & charCodeMask) {
  132.         case ENTER_CODE:
  133.         case RETURN_CODE:
  134.             simulate_key_hit(dp, OK);
  135.             *itemhit = OK;
  136.             return TRUE;
  137.  
  138.         case '\t':
  139.             /* TAB key */
  140.             
  141.             if (key_target == KEYS_ITEM_DROP_KEY) {
  142.                 register INTEGER old = key_target;
  143.                 
  144.                 key_target = 0;
  145.                 SetPort(dp);
  146.                 key_item_proc(dp, old);
  147.                 return FALSE;    /* [sic] */
  148.             }
  149.             else {
  150.                 if (key_target == 0)
  151.                     *itemhit = KEYS_ITEM_LEFT_KEY;
  152.                 else
  153.                     *itemhit = key_target + 1;
  154.                 return TRUE;
  155.             }
  156.             break;
  157.         case '.':
  158.             if (evt->modifiers & cmdKey) {
  159.                 simulate_key_hit(dp, Cancel);
  160.                 *itemhit = Cancel;
  161.                 return TRUE;
  162.             }
  163.             /* continue and process as default case */
  164.         default:
  165.             if (key_target) {
  166.                 /* Set this control to this key */
  167.                 
  168.                 int index = key_target - KEYS_ITEM_LEFT_KEY;
  169.                 register unsigned char code = (evt->message & keyCodeMask) >> 8;
  170.                 register int x;
  171.                 
  172.                 /* Check for clashes */
  173.                 for (x = 0; x < KEY_NUMBER_OF; x++)
  174.                     if (x != index && ctrls.code[x] == code) {
  175.                         SysBeep(5);
  176.                         return FALSE;    /* sic */
  177.                     }
  178.                     
  179.                 ctrls.sym[index] = evt->message & charCodeMask;
  180.                 ctrls.code[index] = code;
  181.                 SetPort(dp);
  182.                 key_item_proc(dp, key_target);
  183.             }
  184.             return FALSE;    /* [sic] */
  185.             break;
  186.         }
  187.         break;
  188.     case activateEvt:
  189.         if (dp != (WindowPtr) evt->message) {
  190.             if (evt->modifiers & activeFlag)
  191.                 window_activate((WindowPtr) evt->message);
  192.             else
  193.                 window_deactivate((WindowPtr) evt->message);
  194.         }
  195.         break;
  196.     case updateEvt:
  197.         if (dp != (WindowPtr) evt->message) 
  198.             window_update((WindowPtr) evt->message);
  199.         break;
  200.     }
  201.  
  202.     return FALSE;
  203. }
  204.  
  205. /*--------------------------------------------------------------------*/
  206.  
  207. void controls_edit(void)
  208. /* Brings up and processes the dialog that lets the user to edit the
  209.    game control keys. */
  210. {
  211.     DialogPtr    dial;
  212.     INTEGER        item;
  213.     INTEGER        x;
  214.     INTEGER        prev;
  215.     struct Ctrls old_key;
  216.     
  217.     for (x = 0; x < KEY_NUMBER_OF; x++) {
  218.         old_key.sym[x] = ctrls.sym[x];
  219.         old_key.code[x] = ctrls.code[x];
  220.     }
  221.     key_target = 0;
  222.     
  223.     /* Load the dialog and set the user items */
  224.     
  225.     dial = GetNewDialog(KEY_DIAL_ID, NIL, (WindowPtr) -1);
  226.     
  227.     install_hilight_button(dial, OK, KEYS_ITEM_HIGHLIGHT);
  228.     for (x = KEYS_ITEM_LEFT_KEY; x <= KEYS_ITEM_DROP_KEY; x++) {
  229.         INTEGER dummy;
  230.         Rect box;
  231.         Handle h;
  232.         
  233.         GetDItem(dial, x, &dummy, &h, &box);
  234.         SetDItem(dial, x, userItem, key_item_proc, &box);
  235.     }
  236.     
  237.     /* Get the height of the default font */
  238.     
  239.     SetPort(dial);
  240.     GetFontInfo(&key_font_info);
  241.  
  242.     do {
  243.         ModalDialog(keys_filter_proc, &item);
  244.     
  245.         switch (item) {
  246.         case OK:
  247.             break;
  248.         case Cancel:
  249.             /* Restore old codes */
  250.             for (x = 0; x < KEY_NUMBER_OF; x++) {
  251.                 ctrls.sym[x] = old_key.sym[x];
  252.                 ctrls.code[x] = old_key.code[x];
  253.             }
  254.             break;
  255.         default:
  256.             SetPort(dial);
  257.             prev = key_target;
  258.             
  259.             key_target = item;
  260.             if (prev)
  261.                 key_item_proc(dial, prev);
  262.             key_item_proc(dial, key_target);
  263.             break;
  264.         }
  265.     } while (item != OK && item != Cancel);
  266.     
  267.     DisposDialog(dial);
  268. }
  269.  
  270. /*====================================================================*/
  271.  
  272. void controls_load(void)
  273. /* Loads the user game controls from the given resource file.  If they
  274.    are not found, nothing is done. */
  275. {
  276.     register OSErr erc;
  277.     LONGINT size;
  278.     struct Ctrls **handle;
  279.     
  280.     handle = (struct Ctrls **) GetResource(PREF_RSRC_TYPE, KEYS_PREF_ID);
  281.     if (handle)
  282.         ctrls = **handle;
  283. }
  284.  
  285. /*--------------------------------------------------------------------*/
  286.  
  287. OSErr controls_save(INTEGER pref_file)
  288. /* Saves the game controls and user settings to the given resource
  289.    file. */
  290. {
  291.     OSErr erc;
  292.     LONGINT size;
  293.     struct Ctrls **handle;
  294.     
  295.     handle = (struct Ctrls **) GetResource(PREF_RSRC_TYPE, KEYS_PREF_ID);
  296.     if (handle != NIL && HomeResFile(handle) == pref_file) {
  297.         RmveResource(handle);
  298.         erc = ResError();
  299.         if (erc != noErr)
  300.             return erc;
  301.         
  302.         DisposHandle(handle);
  303.     }
  304.     
  305.     /* Create new resource */
  306.     
  307.     erc = PtrToHand(&ctrls, &handle, sizeof(ctrls));
  308.     if (erc != noErr)
  309.         return erc;
  310.         
  311.     AddResource(handle, PREF_RSRC_TYPE, KEYS_PREF_ID, "\p");
  312.     erc = ResError();
  313.     if (erc != noErr)
  314.         return erc;
  315.     
  316.     return noErr;
  317. }
  318.  
  319. /*--------------------------------------------------------------------*/
  320.